package com.simen.hellobytes;

import com.simen.hellobytes.model.ByteEndian;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * @author Created by Simen.
 * @date 创建日期 2018/5/26 22:29
 * @modify 修改者 Simen
 */
public class ByteUtil {

    /**
     * @return 返回从src提取的字节部分
     */
    public static byte[] extract(byte[] src, int from) {
        return extract(src, from, src.length - from);
    }

    /**
     * @return 返回从src提取的字节部分
     */
    public static byte[] extract(byte[] src, int from, int length) {
        if (length == 0) {
            return new byte[0];
        }

        byte[] dst = new byte[length];

        System.arraycopy(src, from, dst, 0, length);

        return dst;
    }

    public static int byteToInt(byte b) {
        if (b < 0) {
            return 256 + b;
        }

        return b;
    }

    public static byte[] intToByteArray(int value) {
        return intToByteArray(value, 4);
    }

    public static byte[] intToByteArray(int value, int length) {
        return intToByteArray(value, length, ByteEndian.LittleEndian);
    }

    public static byte[] intToByteArray(int value, ByteEndian byteEndian) {
        return intToByteArray(value, 4, byteEndian);
    }

    public static byte[] intToByteArray(int value, int length, ByteEndian byteEndian) {
        byte[] data = new byte[length > 4 ? 4 : length];

        if (byteEndian == null || byteEndian == ByteEndian.LittleEndian) {
            for (int i = 0; i < data.length; i++) {
                data[i] = (byte) (value >> i * 8);
            }
        } else if (byteEndian == ByteEndian.BigEndian) {
            for (int i = 0; i < data.length; i++) {
                data[i] = (byte) (value >> (data.length - 1 - i) * 8);
            }
        }

        return data;
    }

    public static int byteArrayToInt(byte[] data) {
        return byteArrayToInt(data, 0, data.length);
    }

    public static int byteArrayToInt(byte[] data, int from, int length) {
        return byteArrayToInt(data, from, length, ByteEndian.LittleEndian);
    }

    public static int byteArrayToInt(byte[] data, ByteEndian byteEndian) {
        return byteArrayToInt(data, 0, data.length, byteEndian);
    }

    public static int byteArrayToInt(byte[] data, int from, int length, ByteEndian byteEndian) {
        int[] intArray = new int[length];

        for (int i = 0; i < length; i++) {
            intArray[i] = byteToInt(data[from + i]);
        }

        int result = 0;
        if (byteEndian == null || byteEndian == ByteEndian.LittleEndian) {
            for (int i = 0; i < intArray.length; i++) {
                result += intArray[i] << i * 8;
            }
        } else if (byteEndian == ByteEndian.BigEndian) {
            for (int i = 0; i < intArray.length; i++) {
                result += intArray[i] << (intArray.length - 1 - i) * 8;
            }
        }

        return result;
    }

    /**
     * @return 返回二进制字符串
     */
    public static String byteStr(byte b) {
        String str = "";

        for (int i = 7; i >= 0; i--) {
            str += (b >> i) & 0x1;
        }

        return str;
    }

    public static String bytesToString(byte[] bytes) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            if (i != 0) {
                builder.append(",");
            }
            builder.append(bytes[i]);
        }
        return builder.toString();
    }

    public static byte[] merge(byte[]... arrays) throws IOException {
        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
        for (int i = 0; i < arrays.length; i++) {
            byteOutputStream.write(arrays[i]);
        }
        return byteOutputStream.toByteArray();
    }

}
